var _ = require('underscore'); var print = console.log;  // 向 Python 致敬..., 主要是因为 console.log() 太长
// underscore 本来就是为了充分发挥 JavaScript 的函数式编程特性, 所以也提供了大量 JavaScript 本身没有的高阶函数
// bind(), 针对 var log = console.log; 这种情况, 但我这没什么问题, 见 廖大-underscore.Functions
// partial() 就是为一个函数创建偏函数, 目的是将原函数的某些参数固定住, 可以降低新函数调用的难度
var pow2N = _.partial(Math.pow, 2);    // pow2N(y) 就是根据 Math.pow(x, y) 创建出来的偏函数, 它固定住了原函数的第一个参数
print(pow2N(3), pow2N(5), pow2N(10));  // 8 32 1024
var cube = _.partial(Math.pow, _, 3);  // 固定了第二个参数
print(cube(3), cube(5), cube(10));     // 27, 125, 1000
// memoize() 如果一个函数调用开销很大, 我们就可能希望能把结果缓存下来, 以便后续调用时直接获得结果; 举个例子, 计算阶乘就比较耗时
var factorial = _.memoize(function(n) {
    var s = 1, i = n; while (i > 1) { s = s * i; i --; }
    console.log(n + '! = ' + s); return s;
});
factorial(10);  // 10! = 3628800
factorial(10); factorial(9);  // 第二次调用直接返回上次计算后缓存的结果, 当你计算 factorial(9) 的时候, 仍然会重新计算
var factorial = _.memoize(function(n) {  // 改写成递归的, 就可以缓存每一步了
    console.log('start calculate ' + n + '!...');
    if (n < 2) { return 1; } return n * factorial(n - 1);
});
factorial(10);  // 输出结果说明factorial(1)~factorial(10)都已经缓存了
factorial(9);  // console无输出
// once() 保证某个函数执行且仅执行一次; 若一个方法叫 register(), 在页面上点两个按钮任一个都可以执行, 可以用 once() 保证函数仅调用一次
var register = _.once(function () { print('register'); });
register(); register();  // 只调用了一次
// delay() 可以让一个函数延迟执行, 效果和 setTimeout() 是一样的, 但是代码明显简单了
_.delay(function(){print('hello')}, 2000);  // 2s 后调用
_.delay(print, 4000, 'hello', 'world');  // 可以这样传参数, 相对于上一句是 2s 后执行
